using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections;
using System.Diagnostics;
using System.IO;
using System.Data;
using Adoor.Object;
using Adoor.Object.Query;
using NUnit.Framework;

using Adoor.DAL.Ouvrages;
using Adoor.DAL.Emprunts;
using Adoor.Object.Disconnected;

namespace Biblio.NUnit
{
	[TestFixture]
	public class TestDisconnected : BaseTest
	{
		public ObjectContext Context;
		public StringBuilder SqlTrace;

		[SetUp]
		public void Setup()
		{
			this.Context = CreateContext();
			this.SqlTrace = new StringBuilder();
			Trace.Listeners.Add(new TextWriterTraceListener(new StringWriter(SqlTrace)));

			this.Context.Disconnected = true;
		}

		[TearDown]
		public void TearDown()
		{
			Assert(new Regex("SQL:.*\n").Matches(this.SqlTrace.ToString()).Count == 0);
		}

		// TODO: test in inheritance TestFixture
		//		[Test]
		//		public void TestForeignKeyFactory()
		//		{
		//			Exemplaire exemplaire = CreateExemplaire(Context);
		//			Livre livre = CreateLivre(Context);
		//			exemplaire.Ouvrage = livre;
		//			Assert(exemplaire.Ouvrage == livre);
		//		}

		[Test]
		public void TestForeignKeyFactory()
		{
			Exemplaire exemplaire = CreateExemplaire(Context);
			Emprunt emprunt = CreateEmprunt(Context);
			exemplaire.EmpruntCourant = emprunt;
			Assert(exemplaire.EmpruntCourant == emprunt);
			emprunt = CreateEmprunt(Context);
			exemplaire.EmpruntCourant = emprunt;
			Assert(exemplaire.EmpruntCourant == emprunt);
		}

		[Test]
		public void TestIndirectReferenceFactory()
		{
			Livre livre = CreateLivre(Context);
			Categorie categorie = CreateCategorie(Context);
			livre.Categorie = categorie;
			Assert(livre.Categorie == categorie);
			categorie = CreateCategorie(Context);
			livre.Categorie = categorie;
			Assert(livre.Categorie == categorie);
		}

		[Test]
		public void FindIsNotNullAfterCreate()
		{
			Livre livre = CreateLivre(Context);
			string key = livre.ToString();
			Livre livre2 = (Livre)Context.Find(typeof(Livre), key);
			AssertNotNull(livre2);
		}

		[Test]
		public void FindIsNullAfterDelete()
		{
			Livre livre = CreateLivre(Context);
			string key = livre.ToString();
			Context.LocalStorage.Delete(livre);
			Livre livre2 = (Livre)Context.Find(typeof(Livre), key);
			AssertNull(livre2);
		}

		[Test]
		public void FindIsNullAfterClear()
		{
			Context.Disconnected = true;
			Livre livre = CreateLivre(Context);
			string key = livre.ToString();
			Context.LocalStorage.Clear();
			Livre livre2 = (Livre)Context.Find(typeof(Livre), key);
			AssertNull(livre2);
		}

		[Test]
		public void FindIsIdenticalAfterCreate()
		{
			Livre livre = CreateLivre(Context);
			string key = livre.ToString();
			Livre livre2 = (Livre)Context.Find(typeof(Livre), key);
			AssertSame(livre, livre2);
		}

		[Test]
		public void CollectAfterCreate()
		{
			Livre livre1 = CreateLivre(Context);
			Livre livre2 = CreateLivre(Context);
			Livre livre3 = CreateLivre(Context);
			ICollection livres = Context.LocalStorage.Collect(typeof(Livre));
			Assert(livres.Count == 3);
			int livre1count = 0;
			int livre2count= 0;
			foreach(Livre l in livres)
			{
				Assert(l == livre1 || l == livre2 || l == livre3);
				if (l == livre1)
					++livre1count;
				if (l == livre2)
					++livre2count;
			}
			Assert(livre1count == 1);
			Assert(livre2count == 1);
		}

		[Test]
		public void CollectEmptyAfterCreateAndClear()
		{
			Livre livre1 = CreateLivre(Context);
			string oid1 = livre1.ToString();
			Livre livre2 = CreateLivre(Context);
			string oid2 = livre2.ToString();
			Livre livre3 = CreateLivre(Context);
			string oid3 = livre3.ToString();
			Context.LocalStorage.Clear();
			Assert(Context.LocalStorage.Collect(typeof(Livre)).Count == 0);
		}

		[Test]
		public void TestNxN()
		{
			Livre livre1 = CreateLivre(Context);
			Livre livre2 = CreateLivre(Context);
			Auteur auteur1 = CreateAuteur(Context);
			Auteur auteur2 = CreateAuteur(Context);
			livre1.Auteur.Add(auteur1);
			livre1.Auteur.Add(auteur2);
			auteur2.Livre.Add(livre2);
			Assert(livre1.Auteur.Count == 2);
			Assert(livre1.Auteur[0] == auteur1 || livre1.Auteur[0] == auteur2);
			Assert(livre1.Auteur[1] == auteur1 || livre1.Auteur[1] == auteur2);
			Assert(livre1.Auteur[0] != livre1.Auteur[1]);
			Assert(auteur1.Livre.Count == 1);
			Assert(auteur1.Livre[0] == livre1);
			Assert(auteur2.Livre.Count == 2);
			Assert(auteur2.Livre[0] == livre1 || auteur2.Livre[0] == livre2);
			Assert(auteur2.Livre[1] == livre1 || auteur2.Livre[1] == livre2);
			Assert(auteur2.Livre[0] != auteur2.Livre[1]);
		}

		[Test]
		public void ViewNxN()
		{
			Livre livre1 = CreateLivre(Context);
			Livre livre2 = CreateLivre(Context);
			Auteur auteur1 = CreateAuteur(Context);
			Auteur auteur2 = CreateAuteur(Context);
			livre1.Auteur.Add(auteur1);
			livre1.Auteur.Add(auteur2);
			auteur2.Livre.Add(livre2);
			DataTable table = new DataTable();
			Context.LocalStorage.Fill(table, "select Auteur as OID from Livre, Auteur in Livre.Auteur where Livre = ?", livre1);
			DataView auteurs = table.DefaultView;
			Assert(auteurs.Count == 2);
			Assert(auteurs[0]["OID"] != auteurs[1]["OID"]);
			foreach(DataRowView auteur in auteurs) 
			{
				Assert(string.Compare((auteur["OID"]).ToString(), auteur1.ToString(), true) == 0
                    || string.Compare((auteur["OID"]).ToString(), auteur2.ToString(), true) == 0);
			}
		}

		[Test]
		public void CollectNxN()
		{
			Livre livre1 = CreateLivre(Context);
			Livre livre2 = CreateLivre(Context);
			Auteur auteur1 = CreateAuteur(Context);
			Auteur auteur2 = CreateAuteur(Context);
			livre1.Auteur.Add(auteur1);
			livre1.Auteur.Add(auteur2);
			auteur2.Livre.Add(livre2);
			//ICollection auteurs = Context.LocalStorage.Collect("select Auteur from Livre, Auteur in Livre.Auteur where Livre = :?", livre1);
			ICollection auteurs = Context.LocalStorage.Collect("select Auteur from Livre, Auteur in Livre.Auteur where Livre = ?", livre1);
			Assert(auteurs.Count == 2);
			int auteur1count = 0;
			foreach(Auteur auteur in auteurs) 
			{
				Assert(auteur == auteur1 || auteur == auteur2);
				if (auteur == auteur1)
					++auteur1count;
			}
			Assert(auteur1count == 1);
		}

		[Test, Ignore("too long")]
		public void Test1000Create()
		{
			for(int i = 0; i < 1000; i++)
				CreateLivre(Context);
			Context.LocalStorage.Collect(typeof(Livre));
		}

        //[Test]
        //public void TestTest()
        //{
        //    Test test = CreateTest(Context);
        //    test.Livre = CreateLivre(Context);
        //    test.Auteur = CreateAuteur(Context);

        //    Assert(test.Livre.Test.Count == 1);
        //    Assert(test.Livre.Test[0] == test);
        //    Assert(test.Auteur.Test.Count == 1);
        //    Assert(test.Auteur.Test[0] == test);
        //}
	}
}
